package la.bbs558.controller.user;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import la.bbs558.aop.ratelimit.LimitType;
import la.bbs558.aop.ratelimit.RateLimiter;
import la.bbs558.aop.valid.Check;
import la.bbs558.aop.valid.Valid;
import la.bbs558.controller.base.BaseController;
import la.bbs558.controller.base.Result;
import la.bbs558.entity.UserPush;
import la.bbs558.entity.UserSupervise;
import la.bbs558.entity.enums.RedisKey;
import la.bbs558.entity.params.*;
import la.bbs558.entity.vo.UserVO;
import la.bbs558.service.*;
import la.bbs558.util.IpUtil;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import java.awt.image.BufferedImage;
import java.io.IOException;

/**
 * @Classname UserController
 * @Description 用户
 * @Date 2023/12/15 10:27
 * @Created by weihanmin
 */
@RestController
@RequestMapping("user")
@Check
@Validated
public class UserController extends BaseController {

    @Value("${oss.visit-url}")
    private String ossPrefix;
    @Resource
    private UserService userService;

    @Resource
    private VerifyCodeService verifyCodeService;

    @Resource
    private UserDataService userDataService;

    @Resource
    private UserPushService userPushService;

    @Resource
    private UserSuperviseService userSuperviseService;

    /**
     * 获取oss前缀
     * @return
     */
    @GetMapping("ossPrefix")
    @SaIgnore
    public Result<?> ossPrefix() {
        return Result.success(ossPrefix);
    }

    /**
     * 用户访问
     */
    @GetMapping("visit")
    @SaIgnore
    @RateLimiter(key = "visit:",limitType = LimitType.IP,count = 3,time = 1)
    public Result<?> visit() {
        //   ignore
        return Result.success();
    }

    /**
     * 访问用户信息收集
     */
    @PostMapping("visit/collect")
    @SaIgnore
    @RateLimiter(key = "visitCollect:",limitType = LimitType.IP,count = 3,time = 1)
    public Result<?> visitCollect(@RequestBody UserVisitParams params) {
        Object loginIdDefaultNull = StpUtil.getLoginIdDefaultNull();
        params.setUserId(loginIdDefaultNull == null ? null : Long.parseLong(loginIdDefaultNull.toString()));
        params.setIp(IpUtil.getIp(request));
        userDataService.visitCollect(params);
        return Result.success();
    }

    /**
     * 用户屏蔽、举报
     */
    @PostMapping("supervise")
    @SaIgnore
    @RateLimiter(key = "supervise:",limitType = LimitType.USER_ID,count = 3,time = 1)
    public Result<?> supervise(@RequestBody @Valid UserSupervise userSupervise) {
        boolean insert = userSuperviseService.supervise(userSupervise);
        return Result.success(insert);
    }

    /**
     * 登录
     */
    @PostMapping("signIn")
    @SaIgnore
    @RateLimiter(key = "signIn:",time = 1,count = 1, limitType = LimitType.IP)
    public Result<?> signIn(@RequestBody @Valid UserSignInParams params, HttpServletRequest request) {
        UserVO userVO = userService.signIn(params);
        userService.setLoginDeviceName(request, false);
        return Result.success(userVO);
    }

    /**
     * app登录
     * @param params
     * @return
     */
    @PostMapping("mobile/signIn")
    @SaIgnore
    @RateLimiter(key = "signInForMobile:",time = 1,count = 1, limitType = LimitType.IP)
    public Result<?> signInForMobile(@RequestBody @Valid UserMobileSignInParams params, HttpServletRequest request) {
        UserVO userVO = userService.signInForMobile(params);
        userService.setLoginDeviceName(request, true);
        return Result.success(userVO);
    }

    @GetMapping("isLogin")
    @SaIgnore
    public Result<?> isLogin() {
        return Result.success(StpUtil.isLogin());
    }

    /**
     * 添加推送信息
     * @param cid
     * @return
     */
    @PostMapping("addPushInfo")
    @SaIgnore
    public Result<?> addPushInfo(String cid) {
        if (!StpUtil.isLogin()) return Result.success();
        userPushService.addPushInfo(new UserPush()
                .setUserId(StpUtil.getLoginIdAsLong())
                .setCid(cid));
        return Result.success();
    }

    /**
     * 注册
     * @param params
     * @return
     */
    @PostMapping("signUp")
    @SaIgnore
    @RateLimiter(key = "signUp:",time = 60,count = 30, limitType = LimitType.IP)
    public Result<?> signUp(@RequestBody @Valid UserSignUpParams params) {
        return Result.success(userService.signUp(params));
    }

    /**
     * 退出登录
     * @param cid
     * @return
     */
    @GetMapping("logout")
    public Result<?> logout(@RequestParam(defaultValue = "") String cid) {
        if (Strings.isNotEmpty(cid) && StpUtil.isLogin()) {
            long userId = StpUtil.getLoginIdAsLong();
            userPushService.lambdaUpdate()
                    .eq(UserPush::getUserId, userId)
                    .remove();
        }
        StpUtil.logout();
        return Result.success("退出登录");
    }

    /**
     * 删除用户账号
     * @return
     */
    @PostMapping("cancelAccount")
    public Result<?> cancelAccount() {
        long userId = StpUtil.getLoginIdAsLong();
        userService.removeById(userId);
        StpUtil.logout(userId);
        return Result.success();
    }

    /**
     * 验证邮箱
     * @param email
     * @return
     */
    @PostMapping("validateEmail")
    @SaIgnore
    @RateLimiter(key = "validateEmail:",time = 1,count = 5, limitType = LimitType.IP)
    public Result<?> validateEmail(@NotBlank String email) {
        return Result.success(true);
    }

    /**
     * 验证手机号
     * @param phone
     * @return
     */
    @PostMapping("validatePhone")
    @SaIgnore
    @RateLimiter(key = "validatePhone:",time = 1,count = 5, limitType = LimitType.IP)
    public Result<?> validatePhone(@NotBlank String phone) {
        return Result.success(userService.validatePhone(phone));
    }

    /**
     * 验证忘记密码验证码
     * @return
     */
    @PostMapping("validateForGet")
    @SaIgnore
    @RateLimiter(key = "validateForGet:",time = 60,count = 5, limitType = LimitType.IP)
    public Result<?> validateForGet(@RequestBody UserForgetPasswordParams params) {
        verifyCodeService.verifyCode(RedisKey.FORGET_VERIFY_CODE,params.getEmail(), params.getVerifyCode());
        return Result.success();
    }

    /**
     * 忘记密码
     * @return
     */
    @PostMapping("forGetPassword")
    @SaIgnore
    @RateLimiter(key = "forGetPassword:",time = 60,count = 5, limitType = LimitType.IP)
    public Result<?> forGetPassword(@RequestBody UserForgetPasswordParams params) {
        userService.forGetPassword(params);
        return Result.success();
    }

    @GetMapping("linkCode")
    @SaIgnore
    public void generateLinkCode(@Valid(msg = "code不能为空") String code, HttpServletResponse response) {
        String url = "https://558.la/api/exclusive/" + code;
        BufferedImage bufferedImage = QrCodeUtil.generate(url, 300, 300);
        response.setContentType("image/png");
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            // 将BufferedImage写入输出流
            ImageIO.write(bufferedImage, "png", outputStream);
            // 关闭输出流
            outputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
